namespace("Net");

Net.READY_STATE_COMPLETE = 4;

//TODO: rewrite this with "bind" (like in Dojo)
Net.ContentLoader = function(args)
{
    this.url = args.url;
    this.sid = args.sid;
    this.params = args.params;    
    this.req = null;
    this.onload = args.onload;
    this.onerror = (args.onerror) ? args.onerror : this.defaultError.bind(this);
    this.uploaddata = args.uploaddata;
    this.headers = args.headers;
    this.error = null;
    this.contentType = args.contentType;
    this.response = (args.response)?args.response:new Game.Response();
    this.load(this.url);   
}
 
Net.ContentLoader.prototype.load = function(url)
{
/*
    try
    {
        if (netscape.security.PrivilegeManager.enablePrivilege)
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserAccess");
        else
            alert("Unknown netscape.security.PrivilegeManager.");
    }
    catch(err)
    {
        alert(err);
    }
*/
    if(null == this.onload)
    {
        // Download file specified in request parameters
        // using form to submit data by POST method:
        var cFormId = "__netDownloadForm";
        var form = xGetElementById(cFormId);
        // Create invisible form if it does not exist
        if (! form) {
            form = document.createElement("form");
            form.setAttribute("id", cFormId);
            form.setAttribute("method", "POST");
            form.setAttribute("style", "visibility: hidden");
            form.setAttribute("target", "_blank");
            var xmlRequest = document.createElement("textarea");
            xmlRequest.setAttribute("id", "xmlrequest");
            xmlRequest.setAttribute("name", "xmlrequest");
            form.appendChild(xmlRequest);
            document.documentElement.appendChild(form);
        }
        // Set sending data and submit form
        form.setAttribute("action", url);
        form.firstChild.value = this.params;
        form.submit();
    }
    else
    {// using XMLHttpRequest
        this.req = new XMLHttpRequest();
        if (!this.req)
            return;
        try
        {
            if (this.params)
                this.req.open("POST", url, true);
            else
                this.req.open("GET", url, true);

            var loader = this;
            this.req.onreadystatechange = function()
            {
                loader.onReadyState.call(loader);
            }
            loader.req.setRequestHeader("Content-Type", this.contentType);
            $H(this.headers).each( function(pair) {
                loader.req.setRequestHeader(pair.key, pair.value);
            });
            
            this.req.send(this.params);
        }
        catch(err)
        {
            this.onerror.call(this, err);
        }
    }
}

Net.ContentLoader.prototype.onReadyState = function()
{
    var req = this.req;
    var ready = req.readyState;
    if (ready == Net.READY_STATE_COMPLETE) {
        var httpStatus = req.status;
        if (httpStatus == 200 || httpStatus == 0) {
            this.onload.call(null, this);
        }
        else {
            // Try to parse response and get error data
            if (req.responseXML && typeof(req.responseXML) === "object") {
                var xmlDoc = req.responseXML.documentElement;
                if (xmlDoc) {
                    var nCode = parseInt(Sarissa.getText( xmlDoc.getElementsByTagName("Code")[0] ));
                    var sDescr = Sarissa.getText( xmlDoc.getElementsByTagName("Description")[0] );
                    if (typeof(nCode) === "number" && typeof(sDescr) === "string") {
                        // If session is expired then redirect to login
                        if (nCode === -1) {
                            window.location = "/loginPage5.do?action=expiry";
                            return;
                        }
                        else if (nCode === -2) {
                            window.location = "/loginPage5.do?action=unauth";
                            return;
                        }
                        else {
                            this.error = new LLE.Services.Error(nCode, sDescr);
                        }
                    }
                }
            }
            // Run error handler
            this.onerror.call(null, this);
        }
    }
}

Net.ContentLoader.prototype.defaultError = function(transport)
{
//console.log("transport:");
//console.log(err);
//console.log("this:");
//console.log(this);
//console.log("transport.req.responseXML:");
//console.log(err.req.responseXML);
    alert("error fetching data!"
        + "\n\nreadyState: " + this.req.readyState
        + "\nstatus: " + this.req.status
        + "\nheaders: -->\n" + this.req.getAllResponseHeaders() + "\n<--"
        + (transport ? "\n\n" + transport : "")
    );
}

/**
 *  Tests whether there is an error in response.
 *  It means that server returned http status of an error
 *  and response contained XML with information about error.
 *
 *  @return {Boolean} <code>true</code> if there is an error in response.
 */
Net.ContentLoader.prototype.hasError = function() {
    return (this.error != null);
}

/**
 *  Tests whether response is XML.
 *
 *  @return {Boolean} <code>true</code> if response is XML.
 */
Net.ContentLoader.prototype.hasXMLResponse = function() {
    return (this.req.responseXML != null
            && typeof(this.req.responseXML) === "object"
            && this.req.responseXML.documentElement != null);
}

/**
 *  Tests whether response is correct.
 *  It means that response does not have error and contains XML.
 *
 *  @return {Boolean} <code>true</code> if response is correct.
 */
Net.ContentLoader.prototype.isResponseCorrect = function() {
    return (! this.hasError() && this.hasXMLResponse());
}
